home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / c_lib.arc / PCEXEC.C < prev    next >
Text File  |  1990-08-09  |  5KB  |  153 lines

  1. /**
  2. *
  3. *  Name         pcexec -- Load and execute a program
  4. *
  5. *  Synopsis     ercode = pcexec(pfile,pcmd);
  6. *               int  ercode       Returned DOS 2.0 function error code
  7. *               char *pfile       Name of file to load and execute
  8. *               char *pcmd        Commmand line to pass to the program
  9. *
  10. *  Description  This function loads and executes the program whose file
  11. *               name is specified with pfile.  The program is loaded and
  12. *               executed as if invoked from DOS with the command line
  13. *               specified in pcmd.  The spawned program returns control
  14. *               when either execution ends or Ctrl/Break is pressed.
  15. *               A zero error code indicates successful execution; a
  16. *               positive error code reflects an error from the PCSHRINK
  17. *               function, and negative value from the DOS load function
  18. *               EXEC (4b).
  19. *
  20. *  Returns      ercode            DOS 2.0 function error code
  21. *
  22. *  Version      1.1  (C)Copyright Blaise Computing Inc.  1983, 1984
  23. *
  24. **/
  25. #include <compiler.h>
  26.  
  27. struct segads                          /* Offset, segment address type */
  28. {
  29.   unsigned r;
  30.   unsigned s;
  31. };
  32. #define ADS     struct segads          /* Abbreviation                 */
  33.  
  34. struct dreg
  35. {
  36.   unsigned ax,bx,cx,dx,si,di,ds,es;
  37. };
  38. #define DOSREG  struct dreg
  39.  
  40. #if LAT200
  41. extern ADS _psp;                       /* Program segment prefix       */
  42. #endif
  43. #if CI201A
  44. extern ADS _pspseg;
  45. #endif
  46. #if LAT104 | CI133D
  47. extern unsigned _pgmseg;
  48. #endif
  49.  
  50. int pcexec(pfile,pcmd)
  51. char *pfile,*pcmd;
  52. {
  53.  
  54.     struct parm_block
  55.     {
  56.        unsigned envseg;                /* Segment of environment       */
  57.        ADS      cmd_ads;               /* ADS of command line          */
  58.        ADS      fb1_ads;               /* ADS of first and second file */
  59.        ADS      fb2_ads;               /* control blocks (FCB)         */
  60.     } block_val;
  61.     DOSREG   dos_reg;
  62.     ADS      env_ads,loc_ads;
  63.     int      ercode,cmd_len;
  64.     unsigned size,cs,ss,ds,es;
  65.     char     *pcmd_line,*calloc();
  66. #if CI201A & LDATA
  67.     unsigned long ptrtoabs();
  68. #endif
  69.  
  70.     ercode = pcshrink(&size);          /* Release available memory     */
  71.     if (ercode != 0)
  72.        return(ercode);
  73.  
  74.     /* First set up the parameter block.  Its address is placed in     */
  75.     /* BX register when DOS is called.  Notice that the double word    */
  76.     /* pointers have the offset first then the segment.  This is just  */
  77.     /* like the ADS type.                                              */
  78.  
  79. #if LAT104 | CI133D
  80.     env_ads.s = _pgmseg;               /* The segment address of the   */
  81. #endif                                 /* environment is at offset 2C  */
  82. #if LAT200                             /* in the program segment prefix*/
  83.     env_ads.s = _psp.s;
  84. #endif
  85. #if CI201A
  86.     env_ads.s = _pspseg.s;
  87. #endif
  88.     env_ads.r = 0x2c;
  89. #if LDATA
  90. #if CI201A
  91.     loc_ads.s = (unsigned)((ptrtoabs(&block_val.envseg) & 0xffff0L) >> 4L);
  92.     loc_ads.r = (unsigned)(ptrtoabs(&block_val.envseg) & 0xfL);
  93. #else
  94.     loc_ads.s = (unsigned)(((long)(&block_val.envseg) & 0xffff0L) >> 4L);
  95.     loc_ads.r = (unsigned)((long)(&block_val.envseg) & 0xfL);
  96. #endif
  97. #else
  98.     utsreg(&cs,&ss,&ds,&es);           /* Return segment reg values    */
  99.     loc_ads.s = ds;
  100.     loc_ads.r = &block_val.envseg;
  101. #endif
  102.     utslmove(&env_ads,&loc_ads,2);     /* Copy parent's environment    */
  103.  
  104.     /* The command line must have a leading length byte followed by    */
  105.     /* actual characters making up the string.                         */
  106.  
  107.     cmd_len    = strlen(pcmd);
  108.     pcmd_line  = calloc(cmd_len + 3,1);
  109.     *pcmd_line = (char)cmd_len;
  110.     strcat(pcmd_line,pcmd);            /* pcmd_line is in right format*/
  111. #if LDATA
  112. #if CI201A
  113.     block_val.cmd_ads.s = (unsigned)((ptrtoabs(pcmd_line) & 0xffff0L) >> 4L);
  114.     block_val.cmd_ads.r = (unsigned)(ptrtoabs(pcmd_line) & 0xfL);
  115. #else
  116.     block_val.cmd_ads.s = (unsigned)(((long)(pcmd_line) & 0xffff0L) >> 4L);
  117.     block_val.cmd_ads.r = (unsigned)((long)(pcmd_line) & 0xfL);
  118. #endif
  119. #else
  120.     block_val.cmd_ads.s = ds;
  121.     block_val.cmd_ads.r = (unsigned)pcmd_line;
  122. #endif
  123.     block_val.fb1_ads.r = 0x5c;        /* FCBs are at 5c and 6c within */
  124.     block_val.fb1_ads.s = env_ads.s;   /* the Program Segment Prefix   */
  125.     block_val.fb2_ads.r = 0x6c;
  126.     block_val.fb2_ads.s = env_ads.s;
  127.  
  128.     utinit(&dos_reg);
  129.     dos_reg.ax = 0x4b00;               /* DOS function call 4b         */
  130. #if LDATA
  131. #if CI201A
  132.     dos_reg.es = (unsigned)((ptrtoabs(&block_val) & 0xffff0L) >> 4L);
  133.     dos_reg.bx = (unsigned)(ptrtoabs(&block_val) & 0xfL);
  134.     dos_reg.ds = (unsigned)((ptrtoabs(pfile) & 0xffff0L) >> 4L);
  135.     dos_reg.dx = (unsigned)(ptrtoabs(pfile) & 0xfL);
  136. #else
  137.     dos_reg.es = (unsigned)(((long)(&block_val) & 0xffff0L) >> 4L);
  138.     dos_reg.bx = (unsigned)((long)(&block_val) & 0xfL);
  139.     dos_reg.ds = (unsigned)(((long)(pfile) & 0xffff0L) >> 4L);
  140.     dos_reg.dx = (unsigned)((long)(pfile) & 0xfL);
  141. #endif
  142. #else
  143.     dos_reg.bx = (unsigned)&block_val;
  144.     dos_reg.dx = (unsigned)pfile;
  145. #endif
  146.  
  147.     ercode = -dos(&dos_reg);           /* Return negative error code   */
  148.     free(pcmd_line);
  149.  
  150.     return(ercode);
  151.  
  152. }
  153.